﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MovieBrowser.Model;
using MovieBrowser.Event;
using System.Threading;
using System.Diagnostics;

namespace MovieBrowser.Presentation.Forms.Db
{
    public partial class DbGraph : Form
    {
        public DbGraph()
        {
            InitializeComponent();
        }

        #region Thread Safe Access
        private void DebugTextFired(object sender, EventArgs e)
        {
            if (label1.InvokeRequired)
            {
                label1.Invoke(new EventHandler(DebugTextFired), sender, e);
            }
            else
            {
                var ee = e as DebugTextEventArgs;
                if (ee != null)
                    label1.Text = ee.Text;
            }
        }
        #endregion

        private void button1_Click(object sender, EventArgs e)
        {
            MovieDbEntities db = new MovieDbEntities();
            // create a writer and open the file
            TextWriter tw = new StreamWriter("actors.gexf");

            tw.WriteLine("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
            tw.WriteLine("<gexf xmlns=\"http://www.gexf.net/1.2draft\" version=\"1.2\" xmlns:viz=\"http://www.gexf.net/1.2draft/viz\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.gexf.net/1.2draft http://www.gexf.net/1.2draft/gexf.xsd\">");
            tw.WriteLine("<meta lastmodifieddate=\"2009-03-20\">");
            tw.WriteLine("<creator>Maksud</creator>");
            tw.WriteLine("</meta>");

            tw.WriteLine("<graph mode=\"static\" defaultedgetype=\"undirected\">");
            tw.WriteLine("<nodes>");


            foreach (Person p in db.People)
            {
                tw.WriteLine(string.Format("<node id=\"{0}\" label=\"{1}\">", p.ImdbId, p.Name));
                tw.WriteLine("<attvalues></attvalues>");
                //tw.WriteLine("<viz:size value=\"10.0\"></viz:size>");
                //tw.WriteLine("<viz:position x=\"10000.000000\" y=\"0.000000\" z=\"0.0\"></viz:position>");
                //tw.WriteLine("<viz:color r=\"153\" g=\"153\" b=\"153\"></viz:color>");
                tw.WriteLine("</node>");
            }
            tw.WriteLine("</nodes>");
            tw.WriteLine("<edges>");


            Dictionary<string, Dictionary<string, int>> actor_edge = new Dictionary<string, Dictionary<string, int>>();

            int count = 0;
            foreach (Movie m in db.Movies)
            {
                Person[] actors = db.Actors.Where(o => o.Movie.Id == m.Id).Select(o => o.Person).ToArray();
                for (int i = 0; i < actors.Length; i++)
                {
                    for (int j = i + 1; j < actors.Length; j++)
                    {
                        if (actor_edge.ContainsKey(actors[i].ImdbId))
                        {
                            if (actor_edge[actors[i].ImdbId].ContainsKey(actors[j].ImdbId))
                            {
                                actor_edge[actors[i].ImdbId][actors[j].ImdbId]++;
                            }
                            else
                            {
                                actor_edge[actors[i].ImdbId][actors[j].ImdbId] = 1;
                            }
                        }
                        else if (actor_edge.ContainsKey(actors[j].ImdbId))
                        {
                            if (actor_edge[actors[j].ImdbId].ContainsKey(actors[i].ImdbId))
                            {
                                actor_edge[actors[j].ImdbId][actors[i].ImdbId]++;
                            }
                            else
                            {
                                actor_edge[actors[j].ImdbId][actors[i].ImdbId] = 1;
                            }
                        }
                        else
                        {
                            actor_edge[actors[i].ImdbId] = new Dictionary<string, int>();
                            actor_edge[actors[i].ImdbId][actors[j].ImdbId] = 1;
                        }
                    }
                }
            }

            foreach (var a in actor_edge.Keys)
            {
                foreach (var b in actor_edge[a].Keys)
                {
                    tw.WriteLine(string.Format("<edge id=\"{0}\" source=\"{1}\" target=\"{2}\" weight=\"{3}\" />", count++, a, b, actor_edge[a][b]));
                }
            }

            tw.WriteLine("</edges>");
            tw.WriteLine("</graph>");
            tw.WriteLine("</gexf>");

            tw.Close();
        }

        public void GenerteGexf()
        {
            var watch = new Stopwatch();
            watch.Start();

            MovieDbEntities db = new MovieDbEntities();

            Dictionary<Person, Dictionary<Person, int>> collaboration = new Dictionary<Person, Dictionary<Person, int>>();
            double N = db.People.Count();
            double count = 1;
            foreach (Person p in db.People)
            {
                DebugTextFired(null, new DebugTextEventArgs(string.Format("Completed: {0:0.00}%", (count / N * 100.00))));
                count++;

                collaboration[p] = new Dictionary<Person, int>();
                foreach (Movie m in db.Actors.Where(o => o.Person.Id == p.Id).Select(o => o.Movie))
                {
                    foreach (Person c in db.Actors.Where(o => o.Movie.Id == m.Id).Select(o => o.Person))
                    {
                        if (p.Id != c.Id)
                        {
                            if (collaboration[p].ContainsKey(c))
                            {
                                collaboration[p][c]++;
                            }
                            else
                            {
                                collaboration[p][c] = 1;
                            }
                            //InvokeOnDebugText(p.Name + " collaborated with " + c.Name + " in " + m.Title);
                        }
                    }
                }
            }

            StreamWriter tw = new StreamWriter("actors.gexf", false, Encoding.ASCII);
            tw.AutoFlush = true;
            tw.WriteLine("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
            tw.WriteLine("<gexf xmlns=\"http://www.gexf.net/1.2draft\" version=\"1.2\" xmlns:viz=\"http://www.gexf.net/1.2draft/viz\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.gexf.net/1.2draft http://www.gexf.net/1.2draft/gexf.xsd\">");
            tw.WriteLine("<meta lastmodifieddate=\"2009-03-20\">");
            tw.WriteLine("<creator>Maksud</creator>");
            tw.WriteLine("</meta>");

            tw.WriteLine("<graph mode=\"static\" defaultedgetype=\"undirected\">");
            tw.WriteLine("<nodes>");

            count = 0;
            N = collaboration.Keys.Count;
            foreach (Person pp in collaboration.Keys)
            {
                if (collaboration[pp].Keys.Count > 0)
                {
                    tw.WriteLine(string.Format("<node id=\"{0}\" label=\"{1}\">", pp.ImdbId, pp.Name));
                    tw.WriteLine("<attvalues></attvalues>");
                    //tw.WriteLine("<viz:size value=\"10.0\"></viz:size>");
                    //tw.WriteLine("<viz:position x=\"10000.000000\" y=\"0.000000\" z=\"0.0\"></viz:position>");
                    //tw.WriteLine("<viz:color r=\"153\" g=\"153\" b=\"153\"></viz:color>");
                    tw.WriteLine("</node>");
                }
            }
            tw.WriteLine("</nodes>");
            tw.WriteLine("<edges>");
            foreach (Person pp in collaboration.Keys)
            {
                foreach (Person cc in collaboration[pp].Keys)
                {
                    tw.WriteLine(string.Format("<edge id=\"{0}\" source=\"{1}\" target=\"{2}\" weight=\"{3}\" />", count++, pp.ImdbId, cc.ImdbId, collaboration[pp][cc]));
                }
            }

            tw.WriteLine("</edges>");
            tw.WriteLine("</graph>");
            tw.WriteLine("</gexf>");
            tw.Close();

            watch.Stop();
            DebugTextFired(null, new DebugTextEventArgs(string.Format("Time elapsed: {0}", watch.Elapsed)));
        }

        private void button2_Click(object sender, EventArgs e)
        {
            var t = new Thread(GenerteGexf);
            t.Start();
        }
    }
}
